/*
 * @(#)RedirectResultTestCase.java $version 2010. 8. 11
 *
 * Copyright 2007-2010 NHN Corp. All rights Reserved. 
 * NHN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.nhncorp.usf.core.result;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;

import com.opensymphony.xwork.ActionContext;

import com.nhncorp.lucy.common.config.model.ApplicationInfo;
import com.nhncorp.lucy.web.helper.ServletHelper;
import com.nhncorp.usf.core.config.runtime.ResultPageInfo;
import com.nhncorp.usf.core.config.runtime.ResultPageInfo.DISPATCHER_TYPE;
import com.nhncorp.usf.core.config.ReplaceAllInfo;
import com.nhncorp.usf.core.servlet.ServletContextHolder;
import com.nhncorp.usf.core.util.StringUtil;
import junit.framework.Assert;

/**
 * {@link RedirectResult} TestCase.
 *
 * @author Web Platform Development Team
 */
public class RedirectResultTestCase {
    AbstractResult result = new RedirectResult();
    ResultPageInfo resultPageInfo;

    @BeforeClass
    public static void initialize() throws Exception {
        ApplicationInfo.setNativeEncoding("utf-8");
        ServletContextHolder.set(new MockServletContext());
    }

    @Before
    public void init() {
        MockHttpServletResponse response = new MockHttpServletResponse();
        ServletHelper.setResponse(response);
        response.setCharacterEncoding("utf-8");
        MockHttpServletRequest request = new MockHttpServletRequest();
        ActionContext.getContext().put(ServletHelper.HTTP_REQUEST, request);
        ActionContext.getContext().put(ServletHelper.HTTP_RESPONSE, response);
    }

    /**
     * Form을 갖지 않는 Redirect. includes property를 사용하는 테스트
     *
     * @throws Exception
     */
    @Test
    public void noFormRedirectUseInclude() throws Exception {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/hello.jsp");
        resultPageInfo.getProperties().setProperty("method", "GET");
        resultPageInfo.getProperties().setProperty("target", "_self");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");
        resultPageInfo.getProperties().setProperty("includes", "name, age");
        BeanUtils.populate(result, resultPageInfo.getProperties());

        MockHttpServletResponse response = ((MockHttpServletResponse)ServletHelper.getResponse());
        response.setCharacterEncoding("utf-8");

        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("name", "Gildong,Hong");
            parameterMap.put("age", "100");

            result.execute(resultPageInfo, parameterMap);

            Assert.assertEquals(response.getRedirectedUrl(), "/hello.jsp?age=100&name=Gildong%2CHong");
        } catch(Exception except) {
            except.printStackTrace();
            Assert.fail();
        }
    }

    /**
     * Form을 갖지 않는 Redirect. params property를 사용하는 테스트. params property는 기존방식으로 호환성을 테스트
     *
     * @throws Exception
     */
    @Test
    public void noFormRedirectUseParams() throws Exception {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/hello.jsp");
        resultPageInfo.getProperties().setProperty("method", "GET");
        resultPageInfo.getProperties().setProperty("target", "_self");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");
        resultPageInfo.getProperties().setProperty("params", "name, age");
        BeanUtils.populate(result, resultPageInfo.getProperties());

        MockHttpServletResponse response = ((MockHttpServletResponse)ServletHelper.getResponse());
        response.setCharacterEncoding("utf-8");

        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("name", "Gildong,Hong");
            parameterMap.put("age", "100");

            result.execute(resultPageInfo, parameterMap);

            Assert.assertEquals(response.getRedirectedUrl(), "/hello.jsp?age=100&name=Gildong%2CHong");
        } catch(Exception except) {
            except.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void queryStringRedirect() throws Exception {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/hello.jsp?name=${name}&age=${age}");
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        parameterMap.put("name", "choco");
        parameterMap.put("age", "100");

        try {
            result.execute(resultPageInfo, parameterMap);
            MockHttpServletResponse response = ((MockHttpServletResponse)ServletHelper.getResponse());
            Assert.assertTrue(response.getContentAsString().trim().contains("/hello.jsp?name=choco&age=100"));
        } catch(Exception except) {
            Assert.fail();
        }
    }

     @Test
    public void queryStringRedirectWithReplaceAll1() throws Exception {
        ReplaceAllInfo replaceAllInfo = ReplaceAllInfo.getInstance();
        replaceAllInfo.clear();
        replaceAllInfo.putReplaceInfo("name", "choco-1.0");
        replaceAllInfo.putReplaceInfo("age", "200");

        String src = "/hello.jsp?name=${name}&age=${age}";
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, StringUtil.replacePageSrc(src));
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        parameterMap.put("name", "choco");
        parameterMap.put("age", "100");

        try {
            result.execute(resultPageInfo, parameterMap);
            MockHttpServletResponse response = ((MockHttpServletResponse)ServletHelper.getResponse());
            Assert.assertTrue(response.getContentAsString().trim().contains("/hello.jsp?name=choco&age=100"));
        } catch(Exception except) {
            Assert.fail();
        }
    }

    @Test
    public void queryStringRedirectWithReplaceAll2() throws Exception {
        ReplaceAllInfo replaceAllInfo = ReplaceAllInfo.getInstance();
        replaceAllInfo.clear();
        replaceAllInfo.putReplaceInfo("name", "choco-1.0");
        replaceAllInfo.putReplaceInfo("age", "200");

        String src = "/hello.jsp?name=@{name}&age=@{age}";
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, StringUtil.replacePageSrc(src));
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        parameterMap.put("name", "choco");
        parameterMap.put("age", "100");

        try {
            result.execute(resultPageInfo, parameterMap);
            MockHttpServletResponse response = ((MockHttpServletResponse)ServletHelper.getResponse());
            Assert.assertTrue(response.getContentAsString().trim().contains("/hello.jsp?name=choco-1.0&age=200"));
        } catch(Exception except) {
            Assert.fail();
        }
    }

     @Test
    public void queryStringRedirectWithReplaceAll3() throws Exception {
        ReplaceAllInfo replaceAllInfo = ReplaceAllInfo.getInstance();
        replaceAllInfo.clear();
        replaceAllInfo.putReplaceInfo("name", "choco-1.0");
        replaceAllInfo.putReplaceInfo("age", "200");

        String src = "/hello.jsp?name=${name}&age=@{age}";
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, StringUtil.replacePageSrc(src));
        Map<String, Object> parameterMap = new HashMap<String, Object>();
        parameterMap.put("name", "choco");
        parameterMap.put("age", "100");

        try {
            result.execute(resultPageInfo, parameterMap);
            MockHttpServletResponse response = ((MockHttpServletResponse)ServletHelper.getResponse());
            Assert.assertTrue(response.getContentAsString().trim().contains("/hello.jsp?name=choco&age=200"));
        } catch(Exception except) {
            Assert.fail();
        }
    }

    /**
     * Form 형태의 Redirect. includes property를 사용하는 테스트
     *
     * @throws Exception
     */
    @Test
    public void formRedirectUseIncludes() throws Exception {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/hello.jsp");
        resultPageInfo.getProperties().setProperty("method", "POST");
        resultPageInfo.getProperties().setProperty("target", "this");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");
        resultPageInfo.getProperties().setProperty("includes", "name, age");
        BeanUtils.populate(result, resultPageInfo.getProperties());

        String metaCharset = ApplicationInfo.getMetaCharset();
        if(StringUtil.isEmpty(metaCharset)) {
            metaCharset = "KSC5601";
        }

        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("name", "Gildong,Hong");
            parameterMap.put("age", "100");
            result.execute(resultPageInfo, parameterMap);

            String expectedContent =
                    "<html>\r\n" +
                            "<head>\r\n" +
                            "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + metaCharset + "\">\r\n" +
                            "</head>\r\n" +
                            "<body>\r\n" +
                            "<form name=\"postForm\" method=\"post\" action=\"/hello.jsp\"  >\r\n" +
                            "		<input type=\"hidden\" name=\"age\" value=\"100\"/>\r\n" +
                            "		<input type=\"hidden\" name=\"name\" value=\"Gildong,Hong\"/>\r\n" +
                            "</form>\r\n" +
                            "<script>document.postForm.submit()</script>\r\n" +
                            "</body>\r\n" +
                            "</html>";
            MockHttpServletResponse response = ((MockHttpServletResponse)ServletHelper.getResponse());
            Assert.assertEquals(expectedContent, response.getContentAsString().trim());
        } catch(Exception except) {
            except.printStackTrace();
            Assert.fail();
        }
    }

    /**
     * Form 형태의 Redirect. params property를 사용하는 테스트. params property는 기존방식으로 호환성을 테스트
     *
     * @throws Exception
     */
    @Test
    public void formRedirectUseParams() throws IllegalAccessException, InvocationTargetException {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/hello.jsp");
        resultPageInfo.getProperties().setProperty("method", "POST");
        resultPageInfo.getProperties().setProperty("target", "this");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");
        resultPageInfo.getProperties().setProperty("params", "name, age");
        BeanUtils.populate(result, resultPageInfo.getProperties());

        MockHttpServletResponse response = ((MockHttpServletResponse)ServletHelper.getResponse());
        response.setCharacterEncoding("utf-8");

        String metaCharset = ApplicationInfo.getMetaCharset();
        if(StringUtil.isEmpty(metaCharset)) {
            metaCharset = "KSC5601";
        }

        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("name", "Gildong,Hong");
            parameterMap.put("age", "100");
            result.execute(resultPageInfo, parameterMap);

            String expectedContent =
                    "<html>\r\n" +
                            "<head>\r\n" +
                            "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + metaCharset + "\">\r\n" +
                            "</head>\r\n" +
                            "<body>\r\n" +
                            "<form name=\"postForm\" method=\"post\" action=\"/hello.jsp\"  >\r\n" +
                            "		<input type=\"hidden\" name=\"age\" value=\"100\"/>\r\n" +
                            "		<input type=\"hidden\" name=\"name\" value=\"Gildong,Hong\"/>\r\n" +
                            "</form>\r\n" +
                            "<script>document.postForm.submit()</script>\r\n" +
                            "</body>\r\n" +
                            "</html>";

            Assert.assertEquals(expectedContent, response.getContentAsString().trim());
        } catch(Exception except) {
            except.printStackTrace();
            Assert.fail();
        }
    }
}
